{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 路透社(Reuters)新闻分类"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. load dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T09:01:48.463670Z",
     "start_time": "2020-08-27T09:01:43.792162Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading data from https://s3.amazonaws.com/text-datasets/reuters.npz\n"
     ]
    },
    {
     "ename": "FileNotFoundError",
     "evalue": "[Errno 2] No such file or directory: 'e:/Python/data/Keras/reuters.npz'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mFileNotFoundError\u001b[0m                         Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-2-7a35dc743468>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdatasets\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mreuters\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;33m(\u001b[0m\u001b[0mtrain_data\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrain_labels\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtest_data\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtest_labels\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mreuters\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mload_data\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34mr'e:/Python/data/Keras/reuters.npz'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      3\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      4\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'train:{} test:{}'\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtrain_data\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtest_data\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      5\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'------'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32md:\\programs\\anaconda3\\envs\\tf13-keras\\lib\\site-packages\\keras\\datasets\\reuters.py\u001b[0m in \u001b[0;36mload_data\u001b[1;34m(path, num_words, skip_top, maxlen, test_split, seed, start_char, oov_char, index_from, **kwargs)\u001b[0m\n\u001b[0;32m     53\u001b[0m     path = get_file(path,\n\u001b[0;32m     54\u001b[0m                     \u001b[0morigin\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'https://s3.amazonaws.com/text-datasets/reuters.npz'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 55\u001b[1;33m                     file_hash='87aedbeb0cb229e378797a632c1997b6')\n\u001b[0m\u001b[0;32m     56\u001b[0m     \u001b[1;32mwith\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mload\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mpath\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mallow_pickle\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mf\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     57\u001b[0m         \u001b[0mxs\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlabels\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mf\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'x'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mf\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'y'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32md:\\programs\\anaconda3\\envs\\tf13-keras\\lib\\site-packages\\keras\\utils\\data_utils.py\u001b[0m in \u001b[0;36mget_file\u001b[1;34m(fname, origin, untar, md5_hash, file_hash, cache_subdir, hash_algorithm, extract, archive_format, cache_dir)\u001b[0m\n\u001b[0;32m    223\u001b[0m         \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    224\u001b[0m             \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 225\u001b[1;33m                 \u001b[0murlretrieve\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0morigin\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfpath\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdl_progress\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    226\u001b[0m             \u001b[1;32mexcept\u001b[0m \u001b[0mHTTPError\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    227\u001b[0m                 \u001b[1;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0merror_msg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0morigin\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcode\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmsg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32md:\\programs\\anaconda3\\envs\\tf13-keras\\lib\\urllib\\request.py\u001b[0m in \u001b[0;36murlretrieve\u001b[1;34m(url, filename, reporthook, data)\u001b[0m\n\u001b[0;32m    256\u001b[0m         \u001b[1;31m# Handle temporary file setup.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    257\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0mfilename\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 258\u001b[1;33m             \u001b[0mtfp\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mopen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'wb'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    259\u001b[0m         \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    260\u001b[0m             \u001b[0mtfp\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtempfile\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mNamedTemporaryFile\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdelete\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mFalse\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'e:/Python/data/Keras/reuters.npz'"
     ]
    }
   ],
   "source": [
    "from keras.datasets import reuters\n",
    "(train_data, train_labels),(test_data, test_labels) = reuters.load_data(r'D:/Python/workspace/jupyter/data/reuters.npz')\n",
    "\n",
    "print('train:{} test:{}'.format(len(train_data), len(test_data)))\n",
    "print('------')\n",
    "print(train_data[10])\n",
    "print('------')\n",
    "print(train_labels[:4])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.1 show the content(mud)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-27T09:01:52.259518Z",
     "start_time": "2020-08-27T09:01:51.129540Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading data from https://s3.amazonaws.com/text-datasets/reuters_word_index.json\n"
     ]
    },
    {
     "ename": "FileNotFoundError",
     "evalue": "[Errno 2] No such file or directory: 'e:/Python/data/Keras/reuters_word_index.json'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mFileNotFoundError\u001b[0m                         Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-3-e1007cc999d7>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mdict_words\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdict\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mv\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mk\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mk\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mv\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mreuters\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_word_index\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34mr'e:/Python/data/Keras/reuters_word_index.json'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      2\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m' '\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mdict_words\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'?'\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mtrain_data\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32md:\\programs\\anaconda3\\envs\\tf13-keras\\lib\\site-packages\\keras\\datasets\\reuters.py\u001b[0m in \u001b[0;36mget_word_index\u001b[1;34m(path)\u001b[0m\n\u001b[0;32m    101\u001b[0m         \u001b[0mpath\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    102\u001b[0m         \u001b[0morigin\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'https://s3.amazonaws.com/text-datasets/reuters_word_index.json'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 103\u001b[1;33m         file_hash='4d44cc38712099c9e383dc6e5f11a921')\n\u001b[0m\u001b[0;32m    104\u001b[0m     \u001b[1;32mwith\u001b[0m \u001b[0mopen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mpath\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mf\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    105\u001b[0m         \u001b[1;32mreturn\u001b[0m \u001b[0mjson\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mload\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32md:\\programs\\anaconda3\\envs\\tf13-keras\\lib\\site-packages\\keras\\utils\\data_utils.py\u001b[0m in \u001b[0;36mget_file\u001b[1;34m(fname, origin, untar, md5_hash, file_hash, cache_subdir, hash_algorithm, extract, archive_format, cache_dir)\u001b[0m\n\u001b[0;32m    223\u001b[0m         \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    224\u001b[0m             \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 225\u001b[1;33m                 \u001b[0murlretrieve\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0morigin\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfpath\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdl_progress\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    226\u001b[0m             \u001b[1;32mexcept\u001b[0m \u001b[0mHTTPError\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    227\u001b[0m                 \u001b[1;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0merror_msg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0morigin\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcode\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmsg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32md:\\programs\\anaconda3\\envs\\tf13-keras\\lib\\urllib\\request.py\u001b[0m in \u001b[0;36murlretrieve\u001b[1;34m(url, filename, reporthook, data)\u001b[0m\n\u001b[0;32m    256\u001b[0m         \u001b[1;31m# Handle temporary file setup.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    257\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0mfilename\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 258\u001b[1;33m             \u001b[0mtfp\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mopen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'wb'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    259\u001b[0m         \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    260\u001b[0m             \u001b[0mtfp\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtempfile\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mNamedTemporaryFile\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdelete\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mFalse\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'e:/Python/data/Keras/reuters_word_index.json'"
     ]
    }
   ],
   "source": [
    "dict_words = dict([(int(v),k) for k,v in reuters.get_word_index(r'D:/Python/workspace/jupyter/data/reuters_word_index.json').items()])\n",
    "print(' '.join([dict_words.get(i-3, '?') for i in train_data[0]]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.2 format the input"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "30981\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "mx = 0\n",
    "for line in train_data:\n",
    "    mx = max(max(line), mx)\n",
    "print(mx)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "def vectorize_sequences(sequences, dimension=30982):\n",
    "    results = np.zeros((len(sequences), dimension))\n",
    "    for i, sequence in enumerate(sequences):\n",
    "        results[i, sequence] = 1.\n",
    "    return results\n",
    "x_train = vectorize_sequences(train_data)\n",
    "x_test = vectorize_sequences(test_data)\n",
    "\n",
    "def to_one_hot(labels, dimension=46):\n",
    "    labels = np.zeros((len(labels), dimension))\n",
    "    for i, label in enumerate(labels):\n",
    "        labels[i, label] = 1.\n",
    "    return labels\n",
    "\n",
    "from keras.utils import to_categorical\n",
    "y_train = to_categorical(train_labels)\n",
    "y_test = to_categorical(test_labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.3 split to train and validation dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "x_val = x_train[:982]\n",
    "x_train = x_train[982:]\n",
    "\n",
    "y_val = y_train[:982]\n",
    "y_train = y_train[982:]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2 network\n",
    "## 2.1build model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train on 8000 samples, validate on 982 samples\n",
      "Epoch 1/20\n",
      "8000/8000 [==============================] - 3s 429us/step - loss: 2.6386 - acc: 0.5195 - val_loss: 1.7774 - val_acc: 0.6253\n",
      "Epoch 2/20\n",
      "8000/8000 [==============================] - 3s 393us/step - loss: 1.4234 - acc: 0.7076 - val_loss: 1.3296 - val_acc: 0.7169\n",
      "Epoch 3/20\n",
      "8000/8000 [==============================] - 3s 406us/step - loss: 1.0094 - acc: 0.7879 - val_loss: 1.1243 - val_acc: 0.7566\n",
      "Epoch 4/20\n",
      "8000/8000 [==============================] - 3s 409us/step - loss: 0.7566 - acc: 0.8445 - val_loss: 1.0284 - val_acc: 0.7923\n",
      "Epoch 5/20\n",
      "8000/8000 [==============================] - 3s 421us/step - loss: 0.5793 - acc: 0.8818 - val_loss: 0.9768 - val_acc: 0.7902\n",
      "Epoch 6/20\n",
      "8000/8000 [==============================] - 3s 409us/step - loss: 0.4460 - acc: 0.9091 - val_loss: 0.9697 - val_acc: 0.7974\n",
      "Epoch 7/20\n",
      "8000/8000 [==============================] - 3s 403us/step - loss: 0.3512 - acc: 0.9310 - val_loss: 0.9132 - val_acc: 0.8055\n",
      "Epoch 8/20\n",
      "8000/8000 [==============================] - 3s 421us/step - loss: 0.2816 - acc: 0.9386 - val_loss: 0.9202 - val_acc: 0.8035\n",
      "Epoch 9/20\n",
      "8000/8000 [==============================] - 3s 418us/step - loss: 0.2370 - acc: 0.9469 - val_loss: 0.9176 - val_acc: 0.8157\n",
      "Epoch 10/20\n",
      "8000/8000 [==============================] - 3s 430us/step - loss: 0.1950 - acc: 0.9517 - val_loss: 0.9114 - val_acc: 0.8126\n",
      "Epoch 11/20\n",
      "8000/8000 [==============================] - 3s 435us/step - loss: 0.1767 - acc: 0.9526 - val_loss: 0.9817 - val_acc: 0.7984\n",
      "Epoch 12/20\n",
      "8000/8000 [==============================] - 3s 425us/step - loss: 0.1534 - acc: 0.9544 - val_loss: 0.9419 - val_acc: 0.8177\n",
      "Epoch 13/20\n",
      "8000/8000 [==============================] - 3s 419us/step - loss: 0.1410 - acc: 0.9558 - val_loss: 0.9731 - val_acc: 0.8065\n",
      "Epoch 14/20\n",
      "8000/8000 [==============================] - 3s 428us/step - loss: 0.1320 - acc: 0.9566 - val_loss: 1.0319 - val_acc: 0.7912\n",
      "Epoch 15/20\n",
      "8000/8000 [==============================] - 3s 403us/step - loss: 0.1244 - acc: 0.9580 - val_loss: 0.9934 - val_acc: 0.8147\n",
      "Epoch 16/20\n",
      "8000/8000 [==============================] - 3s 416us/step - loss: 0.1210 - acc: 0.9559 - val_loss: 0.9872 - val_acc: 0.8116\n",
      "Epoch 17/20\n",
      "8000/8000 [==============================] - 4s 442us/step - loss: 0.1169 - acc: 0.9568 - val_loss: 1.0545 - val_acc: 0.8035\n",
      "Epoch 18/20\n",
      "8000/8000 [==============================] - 4s 484us/step - loss: 0.1127 - acc: 0.9561 - val_loss: 1.0181 - val_acc: 0.8177\n",
      "Epoch 19/20\n",
      "8000/8000 [==============================] - 3s 424us/step - loss: 0.1069 - acc: 0.9582 - val_loss: 1.0688 - val_acc: 0.7974\n",
      "Epoch 20/20\n",
      "8000/8000 [==============================] - 3s 409us/step - loss: 0.1070 - acc: 0.9571 - val_loss: 1.1081 - val_acc: 0.7984\n"
     ]
    }
   ],
   "source": [
    "from keras import layers, models\n",
    "\n",
    "model = models.Sequential()\n",
    "model.add(layers.Dense(64,activation='relu', input_shape=(30982,)))\n",
    "model.add(layers.Dense(64,activation='relu'))\n",
    "model.add(layers.Dense(46,activation=\"softmax\"))\n",
    "\n",
    "model.compile(optimizer='rmsprop',\n",
    "             loss='categorical_crossentropy',\n",
    "             metrics=['accuracy'])\n",
    "\n",
    "hisotry = model.fit(x_train,\n",
    "         y_train,\n",
    "         epochs=20,\n",
    "         batch_size=512,\n",
    "         validation_data=(x_val, y_val))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2 show the result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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dOlSNmzYEO9QpBwNGzakTZs21K9fP96hSBXpeEt8Os5ERKQ6KHkkIiIpZenSpTRp0oT27dtjZvEOR6Jwd3Jzc1m6dCkdOnSIdzhSRTreEpuOMxERqS6atiYiIillw4YNtGjRQh9kE5yZ0aJFC1WsJDkdb4lNx5mIiFQXJY9ERCTl6INsctD7lBr0PiY2vT8iIlIdlDwCsrKgfXuoUydcZ2XFOyIREUlWubm5pKenk56ezh577EHr1q233d60aVOZj83OzuaKK64o9zn69u1bLbFOnTqVgQMHVsu2ROIhmY43EZFY0mfa+Ev196DWJ4+ysmDYMFi8GNzD9bBhqfdGi4hIzWjRogWzZs1i1qxZDB8+nKuvvnrb7Z122onNmzdHfWxGRgb33ntvuc/x8ccfV2fIIklLx5uIJItYJhZS4TNtsideauI9iPc+qvXJoxtvhHXrii9bty4sFxGR1FcT/4jPO+88RowYweGHH87111/P559/Tt++fenevTt9+/bl22+/BYpXAo0ePZqhQ4cyYMAAOnbsWOxD7s4777xt/QEDBjBo0CA6depEZmYm7g7ApEmT6NSpE4cccghXXHFFuRVGK1as4JRTTqFr16707t2bOXPmAPDBBx9sq+To3r07eXl5LFu2jP79+5Oenk7nzp2ZNm1ate8zSU21+XhbtGgRhx56KD169KBHjx7FklJjx46lS5cudOvWjZEjRwKwYMECjjrqKLp160aPHj1YuHBh9e8sEQFi/7cp1omFmvhMmwrJr1i+hli/BwmRIHT3pLocdNBBXp3M3MPuL34xq9anERGRGjJv3rwKr/vPf7qnpRX/+5+WFpZXh1GjRvntt9/u5557rp944om+efNmd3dftWqV5+fnu7v7u+++66eddpq7u7///vt+4oknbntsnz59fMOGDb58+XJv3ry5b9q0yd3dGzduvG39pk2b+o8//uhbtmzx3r17+7Rp03z9+vXepk0b//77793d/cwzz9y23aKKPt9ll13mo0ePdnf3KVOmeLdu3dzdfeDAgT59+nR3d8/Ly/P8/HwfN26c/+1vf3N3982bN/vq1aurvI9Ke7+AbE+AMYcu5Y/BdLxV/Hhbu3atr1+/3t3d58+f7wX7c9KkSd6nTx9fu3atu7vn5ua6u3uvXr385Zdfdnf39evXb7u/KirzPokkon/+071du/AZ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PAmob2YtS1lvvLtnuHvGrrvuGsuQRUREdkiLFi3o1asXb731FhCqIM444wzMjDFjxpCdnc2cOXP44IMPtiVeSvPFF1/w7LPP8uWXX/Lyyy8zY8aMbfeddtppzJgxg9mzZ7P//vvz2GOP0bdvX0466SRuv/12Zs2axV577bVt/Q0bNnDeeefx3HPPMXfuXDZv3sxDDz207f6WLVsyc+ZMLr744nKn6owaNYru3bszZ84c/u///o9zzjkHgHHjxvHAAw8wa9Yspk2bRqNGjXjmmWc49thjmTVrFrNnzyY9Pb1K+1QkmlQ83nbbbTfeffddZs6cyXPPPccVV1wBwJtvvsnEiRP57LPPmD17Ntdddx0AmZmZXHrppcyePZuPP/6YVq1a7dhOTTKxbmgNOg29iAjEsGG2mRnwGPCNu98ZZZ09gF/d3c2sFyGZlRurmEREpJa56iqYNat6t5meDnffXeYqBVNpTj75ZJ599lkef/xxAJ5//nnGjx/P5s2bWbZsGfPmzaNr166lbmPatGmceuqppEXmS5x00knb7vvqq6/4y1/+wsqVK1mzZg3HHntsmfF8++23dOjQgX333ReAc889lwceeICrrroKCB+OAQ466CBefnm773qKmT59Oi+99BIARxxxBLm5uaxatYp+/foxYsQIMjMzOe2002jTpg09e/Zk6NCh5Ofnc8oppyh5lOp0vAE7frzl5+dz2WWXMWvWLOrWrcv8+fMBmDx5Mueff/62GJs3b05eXh4//fQTp556KgANGzYsM7ZUVBMNrUVEJLaVR/2AIcARZjYrcjnBzIab2fDIOoOAr8xsNnAvcKa7ewxjEhERiblTTjmFKVOmMHPmTNavX0+PHj344YcfGDduHFOmTGHOnDmceOKJbNiwoczthO9htnfeeedx//33M3fuXEaNGlXudsr719qgQQMA6taty+bNmyu9LTNj5MiRPProo6xfv57evXuTk5ND//79+fDDD2ndujVDhgzhqaeeKnPbIlWRasfbXXfdxe67787s2bPJzs5m06ZN27ZbMkYNm9XQWkSkpsSs8sjdpwOl/xcuXOd+4P5YxSAiIrVcORULsbLzzjszYMAAhg4duq1x7+rVq2ncuDHNmjXj119/5c0332TAgAFRt9G/f3/OO+88Ro4cyebNm3nttde46KKLAMjLy6NVq1bk5+eTlZVF69bhZKZNmjQhLy9vu2116tSJRYsWsWDBAvbee2+efvppDjvssCq9tv79+5OVlcVNN93E1KlTadmyJU2bNmXhwoV06dKFLl268Mknn5CTk0OjRo1o3bo1F154IWvXrmXmzJnbprlJCtLxBuz48bZq1SratGlDnTp1mDBhAlu2bAHgmGOO4a9//Stnn302aWlprFixgubNm9OmTRsmTpzIKaecwsaNG9myZcu26qTaYMyY0OOo6NQ1NbQWEal+NXK2NRERkdrmrLPOYvbs2Zx55pkAdOvWje7du3PggQcydOhQ+vXrV+bje/TowRlnnEF6ejqnn346hx566Lb7brnlFg4++GCOPvpoOnXqtG35mWeeye2330737t2LNc1t2LAhTzzxBIMHD6ZLly7UqVOH4cOHUxWjR48mOzubrl27MnLkSCZMmACE06N37tyZbt260ahRI44//nimTp26rYH2Sy+9xJVXXlml5xQpTyodb5dccgkTJkygd+/ezJ8/n8aNGwNw3HHHcdJJJ5GRkUF6evq2fklPP/009957L127dqVv37788ssvFX6uVKCG1iIiNcOSrdw1IyPDs7Oz4x2GiIgkqG+++Yb9998/3mFIBZX2fpnZF+6eEaeQJIrSxmA63pKD3icREamIssZgqjwSEREREREREZGolDwSEREREREREZGolDwSEREREREREZGolDwSEZGUk2z9/GorvU+pQe9jYtP7IyIi1UHJIxERSSkNGzYkNzdXH5gSnLuTm5tLw4YN4x2K7AAdb4ktEY6zrCxo3x7q1AnXWVlxC0VERHZAvXgHICIiUp3atGnD0qVLWb58ebxDkXI0bNiQNm3axDsM2QE63hJfPI+zrCwYNgzWrQu3Fy8OtwEyM+MSkoiIVJGSRyIiklLq169Phw4d4h2GSK2g403KcuONhYmjAuvWheVKHomIJBdNWxMRERERkWq3ZEnllouISOJS8khEREQkxZjZcWb2rZktMLORpdz/X2b2ipnNMbPPzaxzPOKU1Na2beWWi4hI4lLySERERCSFmFld4AHgeOAA4CwzO6DEan8GZrl7V+Ac4J6ajVJqgzFjIC2t+LK0tLBcRESSi5JHIiIiIqmlF7DA3b93903As8DJJdY5AJgC4O45QHsz271mw5RUl5kJ48dDu3ZgFq7Hj1e/IxGRZKSG2SIiIiKppTXwY5HbS4GDS6wzGzgNmG5mvYB2QBvg1xqJUGqNzEwli0REUoEqj0RERERSi5WyzEvcvg34LzObBVwOfAls3m5DZsPMLNvMspcvX179kYqIiEhSUOWRiIiISGpZCuxZ5HYb4OeiK7j7auB8ADMz4IfIhRLrjQfGA2RkZJRMQImIiEgtocojERERkdQyA9jHzDqY2U7AmcCrRVcws10i9wH8N/BhJKEkIiIish1VHomIiIikEHffbGaXAW8DdYHH3f1rMxseuf9hYH/gKTPbAswDLohbwCIiIpLwlDwSERERSTHuPgmYVGLZw0V+/gTYp6bjEhERkeSkaWsiIiIiIiIiIhKVkkciIiIiIiIiIhKVkkciIiIiIrVUVha0bw916oTrrKx4RyQiIolIPY9ERERERGqhrCwYNgzWrQu3Fy8OtwEyM+MXl4iIJB5VHomIiIiI1EI33liYOCqwbl1YLiIiUpSSRyIiIiIitdCSJZVbLiIitZeSRyIiIiIitVDbtpVbLiIitZeSRyIiIiIitdCYMZCWVnxZWlpYLiIiUpSSRyIiIiIitVBmJowfD+3agVm4Hj9ezbJFRGR7OtuaiIiIiEgtlZmpZJGIiJRPlUciIiIiIiIiIhKVkkciIiIiIiIiIhKVkkciIiIiIiIiIhKVkkciIiIiIiIiIhKVkkciIiIiIiIiIhKVkkciIiIiIiIiIhKVkkciIiIiIiIiIhKVkkciIiIiIiIiIhKVkkciIiIiIiIiIhKVkkciIiIiIiIiIhKVkkciIiIiIiIiIhJVzJJHZranmb1vZt+Y2ddmdmUp65iZ3WtmC8xsjpn1iFU8IiIiIiIiIiJSefViuO3NwDXuPtPMmgBfmNm77j6vyDrHA/tELgcDD0WuRUREREREREQkAcSs8sjdl7n7zMjPecA3QOsSq50MPOXBp8AuZtYqVjGJiIiIiCSTrCxo3x7q1AnXWVnxjkhERGqjWFYebWNm7YHuwGcl7moN/Fjk9tLIsmU1EZeIiIiISKLKyoJhw2DdunB78eJwGyAzM35xiYhI7RPzhtlmtjPwEnCVu68ueXcpD/FStjHMzLLNLHv58uWxCFNEREREJKHceGNh4qjAunVhuYiISE2KafLIzOoTEkdZ7v5yKassBfYscrsN8HPJldx9vLtnuHvGrrvuGptgRUREREQSyJIllVsuIiISK7E825oBjwHfuPudUVZ7FTgncta13sAqd9eUNRERERGp9dq2rdxyERGRWIll5VE/YAhwhJnNilxOMLPhZjY8ss4k4HtgAfAIcEkM4xERERERSRpjxkBaWvFlaWlhuYiISE2KWcNsd59O6T2Niq7jwKWxikFEREREJFkVNMW+8cYwVa1t25A4UrNsERGpaTVytjUREREREam8zEwli0REJP5ifrY1ERERERERERFJXkoeiYiIiIiIiIhIVEoeiYiIiIiIiIhIVEoeiYiIiIiIiIhIVEoeiYiIiIiIiIhIVEoeiYiIiIiIiIhIVEoeiYiIiCm/dC8AACAASURBVIiIiIhIVEoeiYiIiIiIiIhIVEoeiYiIiIiIiIhIVEoeiYiIiIiISGJbuhQWLgT3eEciyWrzZpgzBzZtinckSUnJIxERERERkXjavBmWL4f8/HhHkng+/RQGD4Z27WDvvaF9ezj/fHj6afj553hHJ4kuPx/eeQeGDYNWraBbN9hrL7jnHli7Nt7RJZV68Q5ARERERESk1vnpJ3jrrXB5911YtSosb9IEmjcPlxYtCn8ueilt+U47xff1VKctW2DiRLjjDvjkE9hlF7j22pBAeu89eO01ePLJsG6nTnDEEXDkkTBgQNgXtdHatfD447ByZfTfm2bNwCzekcZefn74PXnhBXjlFVixAnbeGQYODL8jzzwDV10Ft9wCV14Jl10G//Vf8Y464ZknWdlfRkaGZ2dnxzsMERERiREz+8LdM+IdhxSnMZjIDtq0CT76KCSL3nwT5s4Ny1u3huOOg65dwwf/FSuiX7Zsib79xo3LTjbtsQcccwzstlvNvN6qWLMGnngC7r4bvv8eOnQIH/KHDg0f/gts3RqmH02ZEpIEH34YHmsG3bsXJpMOPTTsl1S2eXNIGo0eDcuWlb1u3bohSVKRZGTRZc2aQZ0En7S0aVP4fXjhhZB4/P33kIj94x9D5dqxx0KjRoXrf/wx3HorvP56+N0aPhyuvhr+8If4vYYEUNYYTMkjERERSShKHiUmjcFEqmDJkpAoeustmDw5JDjq14dDDgkJo+OPh86dK1YN4g6rV0dPLOXmRl++eXPYRp06cNhhMGgQnHZaSCglgp9/hvvug3/8I3zo790brrkGTj01JDzKk58PM2aE5MGUKaFaadOmsK8PPjgkko44Imw3VSq03OHf/4YbboCcHOjXD8aOhYyMsA8r8/uxYkX43YrGrDDptOeekJ4eknTp6aHyq379mnvdRW3cGI6rF14I+2LlSmjaFE46KSSMjjkGGjYsextz58Jtt8Gzz0K9enDuuXDddWGKZC2k5FFF/Oc/oVw0M7P6ty0iIiIVpuRRYlLySKQCNm4MVTAF1UXffBOWt20bEkXHHx+SGE2a1FxM7mFK04IF8PLL4YN2Tk5ICPTvHz5kn3Za6AdT02bPhjvvhH/9K1RVnXpqSBr16bNj2123LlR5vfdeSCZ98UWoVkpLC4m7gmRS9+4VS04lmo8/DgmOjz4KyZvbbgsJkx2Zkpafv33lW8mEU25uqAibMwc2bAiPa9AgJECLJpS6do3d7/iGDeFz+wsvwKuvhumezZrBySeH3+Wjjw4xVdb338Ptt4fKt/z8sK2RI8PrqUWUPKqI668PvyyzZoVfdhEREYkLJY8Sk5JHIlF8/31hddF774XExU47hQqf448PFUadOiVOrxl3mDcvfPh+4YXws1lIqhQkklq3ju3zv/126Gc0eXKYVjZ0aJie1rFjbJ5z5Ur44IPCZNLXX4flu+wSeuAUJJP23z9x3qfSfPttqDR65ZVQNfa//xv2Xb0abmW8eTPMnx8+O8+aBV9+GS65ueF+s1C5UzShlJ5e9QTlhg3hd6YgYZSXF967U04Jv7NHHVV9FWW//AJ33QUPPRSe5/jjwz4/9NDq2X6CU/KoIlasCL/gPXuGX0wRERGJCyWPEpOSR5KQ8vNDdc+8eaGCZOedS780blx9PVvWr4epUwuri777Lizv2LGwumjAgOTptTNvHrz4Yvhg/tVXYVm/fuFD+emnQ5s21fM8GzdCVlaoNPr669Bb5vLL4aKLar5Z8S+/wPvvFyaTfvghLG/TBs44I8xGSU9PnETSsmUhUfToo6F66rrrQn+eRPodcw/TD7/8sjChNGtWSK4W2H337RNK++xT+rG5fn04xl54ITRIX7MmTJsrSBgdcURspyCuXAkPPBD6b/32WzgmbrgBTjghcX4vYkDJo4q66y4YMSL8kh57bGyeQ0RERMqk5NGOM7PjgHuAusCj7n5bifubAf8E2hLOvjvO3Z8oa5tKHknc5eWFaU5Fqx2++ir0tqmItLQwlSZagqnopeR6aWlhqs6bb4YKlg0bQi+Vww8v7F20zz6xff01ISenMJE0Z05Y1qdP+LA+aFDod1NZv/0WqjgeeAB+/TXM8rjmGjjzzMTpP/TDDyGR9Oqr4T3Ozw9VSJmZcNZZsauIKk9eXpgdc8cd4ff84ovhpptg113jE09VrFpVeNwWJJS+/jrsYwgJsK5dC5NKTZqE/kWvvx4SRi1ahOmMgweH462m+yutWwePPQbjxoUeZl27hulsgwfXfMVXDVDyqKI2boQDDgj/HGbNSs75ryIiIklOyaMdY2Z1gfnA0cBSYAZwlrvPK7LOn4Fm7n69me0KfAvs4e5RP4UreSQ1atmy4h82v/wy9Owp0KJFYfVC9+6h50qdOuHDZrRLXl759+flFTaXLs1++xUmi/r3L372plQzf35IIr34YngPIDSfLkgktWtX/uPvugsmTAhVJMcdF5JGRx6Z2JUbubnhNT/zTOhfBSGBlpkJf/pTzSRuNm2C8ePhr3+F5ctDNdSYMbDXXrF/7pqwaVOoeCuaCJ41q7Bpd8uWYfrk4MGhii8RkjT5+aE31223hWrHjh1DBdi555bflDuJKHlUGS++GH5JH30ULrggds8jIiIipVLyaMeYWR9gtLsfG7l9A4C731pknRuAPYFLgfbAu8C+7r412naVPJKY2Lo1TPsq+gFy1qxQoVKgY8ftp7q0bh27BMSmTaUnl9q3j18FSrx99134nPTiizBzZljWs2dhIqlDh7DMHaZNC5Uyr70WqkSGDAlTrA48MH7xV9WSJSFhkJUVzspVt244g1dmZmjQvPPO1ft87iFh9+c/w8KFIXEydmzY16nOHRYtCsmyHj0SI2FUmq1bQ4XarbfC55+H3lMjRsDw4TXbCD9GlDyqDPcwn3HRopAtr+4/CCIiIlImJY92jJkNAo5z9/+O3B4CHOzulxVZpwnwKtAJaAKc4e5vlLKtYcAwgLZt2x60ePHiGngFkrLWrw/TzIpWG8yZE84EBiHRcOCBxRNF3bqFMylJ4li4sDCRVPC57KCDQjXWW2+FZS1awCWXwKWXhj43qWDu3FCN9MwzIamUlhb675x9dkgo7eh0qqlTQyXLjBmhku7vfw/7NJGrtGoz99A369ZbQ+P3XXaByy6DK66oWHXali0hUV3ysnFj6cuLXurXD/3IYkDJo8r65BPo2xdGj4ZRo2L7XCIiIlKMkkc7xswGA8eWSB71cvfLi6wzCOgHjAD2IlQedXP31dG2q8ojqbD8/DDFbN68cPn665A0yskJH5gAmjYtrCIqSBYdcEDi9MCRivnhh8JE0uefh75PI0bAOeeE5Eoq2roVPvooJJGefz6ceKllyzCl7eyzw+fIyiR8vvoq9NB5443QsPuWW0K1llqoJI8ZM8J0tldeCVPYDjig/ETQ1qiFvuX7wx/gp5+qL/4ilDyqij/9KRzA330X3hwRERGpEUoe7ZgKTlt7A7jN3adFbr8HjHT3z6NtV8kj2c6mTWGsXDRJNG9eqN4vaIYLYUpTQUVRQaKoffvqO/uZJIbffw9VYrXpfd20KZyp+5lnQpPn9evD7/bZZ4dLWVP1li6Fm28OPaGaNAlT1S6/PLX7aKW6b76Be+4J7+1OOxW/NGiw/bLyLtEe07Bh+D2LASWPqmLhwtBh/5xzQv8jERERqRFKHu0YM6tHaJh9JPAToWH22e7+dZF1HgJ+dffRZrY7MJNQefRbtO0qeVSLbdwYkkQFyaGCRNF33xU2lzYL/YAOPDB8637AAeHn/fZLrNOJi8RKXh5MnBj6I02eHKrsunUrPGNbmzZhvZUrQ5XKPfeE6pPLLguJoxYt4hu/CEoeVd2IEXD33WFOdteuNfOcIiIitZySRzvOzE4A7gbqAo+7+xgzGw7g7g+b2R+AJ4FWgBGqkP5Z1jaVPCpdVhbceGNogdK2bTghUmZmNT7BggXhy8wffyz/NPMVOQ19kybh2+zSptVs2BCqhkomiRYsKJxuVqdOOONTaUkiVUyIBL/+Gqa0ZWXBZ5+F461/f+jdGx55JFRpZWaGKWoxqiARqQolj6pqxQrYe2/o1Ss0fxMREZGYU/IoMSl5tL2sLBg2DNatK1yWlhbOsF0tCaT33gtnsjKDk04KjaXLOv18RdWtu31SafXqUHlf0Iejbt0wDi6ZJNp335Q6LbVIzC1YUHjGtm+/Dc21//73MIVTJMEoebQj7rorVCC99RYce2zNPa+IiEgtpeRRYlLyaHvt20NpJ6Br1y6cuHeHPPhgOGtPp07htNDlnSJ+69bQb6W0U8yXlmgqeWnYsHiiaN99Q4WSiFQPd8jNDc21RRJUWWOwejUdTNK55BK4/3649lo46ih1vRcRERERIExVq8zyCsnPhyuvhIcegoEDQ7VC06blP65OndBbqHHj1Dk1ukgqMVPiSJJaLWqFX0UNGoSGZnPnwpNPxjsaEREREUkQbdtWbnm5cnNDpftDD8F114XmuxVJHImIiMSYkkcVMWgQ9OkDN91UufnkIiIiIpKyxowJPY6KSksLyytt3jw4+GD46CN46qnQE0UV7yIikiCUPKoIM7jjDli2LFyLiIiISK2XmRmaY7drF4aL7dpVsVn2pEnhLExr1sDUqTBkSCzCFRERqTIljyqqTx8YPBjGjg1JJBERERGp9TIzQ3PsrVvDdaUSR+4wblzobbT33jBjRhhzioiIJBgljyrj1ltDE8Obbop3JCIiIiKSzDZuhPPPDydlOf10mDYN9twz3lGJiIiUSsmjythrL7jsMnj8cZgzJ97RiIiIiEgy+vVXOOIImDABRo+G554LZ0kTERFJUEoeVdZf/gLNmoUzYIiIiIiIVMasWdCzJ3z5JbzwAowaBXU0JBcRkcSm/1SV1bx5mLb29tvhIiIiIiJSES+/DP36hV5H06eHM/qKiIgkASWPquLSS6FjxzBHfcuWeEcjIiIiIonMHW65JfQ26to1NMbu0SPeUYmIiFSYkkdV0aAB3HYbzJ0b5qqLiIiIiJRm3To46yy4+WYYMgTefx/22CPeUYmIiFSKkkdVNWgQ9O4deiCtWRPvaEREREQk0SxdCv37w/PPw9ix4UvHhg3jHZWIiEilxSx5ZGaPm9l/zOyrKPcPMLNVZjYrcrk5VrHEhBnccQcsWxauRUREREQKfPZZaIw9fz68+mpod2AW76hERESqJJaVR08Cx5WzzjR3T49c/hrDWGKjb99QgTR2bEgiiYiIiIhkZcFhh0FaGnzyCQwcGO+IREREdkjMkkfu/iGwIlbbTxi33Qb5+WEeu4iIiIjUXlu3wg03wP/7f6G9wWefwYEHxjsqERGRHRbvnkd9zGy2mb1pZlH/s5rZMDPLNrPs5cuX12R85dtrL7jsMnj88dBAW0RERERqn7w8OPXU8MXiRRfBO+9Ay5bxjkpERKRaxDN5NBNo5+7dgPuAidFWdPfx7p7h7hm77rprjQVYYX/5CzRtGuayi4iIiEjt8sMPoZ3BG2/A/ffDQw/BTjvFOyoREZFqE7fkkbuvdvc1kZ8nAfXNLDm/nmneHG66Cd5+O1xEREREpHb47DPo1SucWe2tt+DSS9UYW0REUk7ckkdmtodZ+M9qZr0iseTGK54dduml0KFDqD7asiXe0YiIiIhIrL3zDhx5JDRrBp9/DkcdFe+IREREYqJCySMza2xmdSI/72tmJ5lZ/XIe8y/gE2A/M1tqZheY2XAzGx5ZZRDwlZnNBu4FznR3r/pLibMGDcIc97lzYcKEeEcjIiIiKaAqYzCpIc8/H86itvfeMH067LNPvCMSERGJmYpWHn0INDSz1sAU4HzgybIe4O5nuXsrd6/v7m3c/TF3f9jdH47cf7+7H+ju3dy9t7t/vCMvJCEMHhzOrPGXv8DatcXuysqC9u2hTp1wnZUVlwhFREQkuVR6DCY14OGH4cwzw7hv6lTYY494RyQiIhJTFU0embuvA04D7nP3U4EDYhdWkjKDO+6AZctg3Lhti7OyYNgwWLwY3MP1sGFKIImIiEi5NAZLJO4wZgxcfDGceGLodbnLLvGOSkREJOYqnDwysz5AJvBGZFm92ISU5Pr2hUGDYOzYkEQCbrwR1q0rvtq6dWG5iIiISBk0BksUW7fCiBGhwnzIEHj5ZWjUKN5RiYiI1IiKJo+uAm4AXnH3r82sI/B+7MJKcrfeCvn5cPPNACxZUvpq0ZaLiIiIRGgMlgjy8+Hcc+Huu+Gqq+DJJ6G+Wk+JiEjtUaFvrtz9A+ADgEjTxt/c/YpYBpbU9t47nH3t3nvhiito27YLixdvv1rbtjUfmoiIiCQPjcESwPr18Kc/weuvhylrN9wQWhWIiIjUIhU929ozZtbUzBoD84Bvzeza2IaW5G66CZo2heuuY8wYSEsrfndaWhh/iIiIiESjMVicrVwJxx4Lb7wRmmT/+c9KHImISK1U0WlrB7j7auAUYBLQFhgSs6hSQfPmIYH01ltk7voO48dDu3ZhvNGuHYwfD5mZ8Q5SREREEpzGYPHyyy8wYAB8+ik89xxcdFG8IxIREYmbiiaP6ptZfcLA5d/ung947MJKEZdeCh06wP/8D5lnbmHRotBrcdEiJY5ERESkQjQGi4fvv4dDDoEFC0LV0eDB8Y5IREQkriqaPPoHsAhoDHxoZu2A1bEKKmU0aAC33QZz58KECfGORkRERJKPxmA1bc4c6NcPfv8dpkyBo4+Od0QiIiJxZ+5V+/LKzOq5++ZqjqdcGRkZnp2dXdNPW3Xu0KdPOLXad99B48bxjkhERCShmdkX7p4R7zgSlcZgMfTRRzBwYBivvfMOHHBAvCMSERGpMWWNwSraMLuZmd1pZtmRyx2Eb8CkPGZw552wbBnccUe8oxEREZEkojFYDZo0KVQZ7bZbSCIpcSQiIrJNRaetPQ7kAX+KXFYDT8QqqJTTty8MGgRjx4bqIxEREZGK0RisJjzzDJx8Muy/P0yfHs5uIiIiIttUNHm0l7uPcvfvI5f/BTrGMrCU8/e/hx5IvXvDe+/FOxoRERFJDhqDxdp994UzmRxyCLz/Puy6a7wjEhERSTgVTR6tN7NDCm6YWT9gfWxCSlEdO8Lnn8Puu8Mxx8CDD8Y7IhEREUl8GoPFijuMGgVXXAGnnAJvvglNm8Y7KhERkYRUr4LrDQeeMrNmkdu/A+fGJqQUttde8OmncPbZcOml8NVXcM89UL9+vCMTERGRxKQxWCxs3QqXXx6+zBs6FP7xD6hX0WGxiIhI7VOhyiN3n+3u3YCuQFd37w4cEdPIUlXTpvDvf8N118FDD8Gxx0JubryjEhERkQSkMVgMbNoUpqk9+CBcey08+qgSRyIiIuWo6LQ1ANx9tbuvjtwcEYN4aoe6dUMPpKeeCmfz6NUL5s2Ld1QiIiKSoDQGqyZr14bG2M8+G8ZiY8eGM+OKiIhImSqVPCpB/2l31JAh8MEHYSDTuze88Ua8IxIREZHEpzFYVaxYAUcfDe+8E6qNrrsu3hGJiIgkjR1JHnm1RVGb9e4NM2bAPvvAH/8It98eGjiKiIiIlE4Dhcr66Sfo3x+++AJefBEuuCDeEYmIiCSVMid4m1kepQ9QDGgUk4hqoz33hGnT4Pzzw7dgc+fC+PHQsGG8IxMREZE40BisGv3wAxxxROgx+dZbcPjh8Y5IREQk6ZSZPHL3JjUVSK2Xlhbm33fuDDffDN99B6+8AnvsEe/IREREpIZpDFaNRowIU9befx8OOije0YiIiCSlHZm2JtXNDG66KZRTz5kDPXvCzJnxjkpEREQkOX3zDUycCFdeqcSRiIjIDlDyKBGdfno4C5sZHHIIPP98vCMSERERSToLLxrLemvErrdcQfv2kJUV74hERESSk5JHiSo9PTTS7t4dzjgjTGXbujXeUYmIiIgkhVfuWULbaf9kvF/Ib7Rk8WIYNkwJJBERkapQ8iiR7b47vPdeaKR9yy0weDCsXRvvqEREREQS3u833QnAHVyzbdm6dXDjjfGKSEREJHkpeZToGjSAxx6DO+8Mc/b79YPFi+MdlYiIiEji+u03zsh7hCwy+ZG2xe5asiROMYmIiCQxJY+SgRlcfTW88UY43WyvXqEnkoiIiEgpzOw4M/vWzBaY2chS7r/WzGZFLl+Z2RYzax6PWGPivvtozDrGct12d7VtW8r6IiIiUiYlj5LJccfBZ59B06Zw+OHwxBPxjkhEREQSjJnVBR4AjgcOAM4yswOKruPut7t7urunAzcAH7j7ipqPNgbWrIH77uPHg05hcVqxl01aGowZE6e4REREkpiSR8mmU6eQQDrsMBg6FK65BrZsiXdUIiIikjh6AQvc/Xt33wQ8C5xcxvpnAf+qkchqwvjx8Pvv7Hn/9YwfD+3ahSLudu3CXZmZ8Q5QREQk+Sh5lIyaN4c334TLLw+9kAYOhFWr4h2ViIiIJIbWwI9Fbi+NLNuOmaUBxwEv1UBcsbdxI9xxBwwYAL17k5kJixaFE9YuWqTEkYiISFUpeZSs6tWDe++Ff/wDJk+G3r3hu+/iHZWIiIjEn5WyzKOs+0fgo2hT1sxsmJllm1n28uXLqy3AmMnKgp9/hhtuiHckIiIiKUXJo2Q3bFhIHi1fDgcfDI88Anl58Y5KRERE4mcpsGeR222An6OseyZlTFlz9/HunuHuGbvuums1hhgDW7bA3/8O3bvD0UfHOxoREZGUouRRKjjsMJgxAzp2DMmkVq1CP6SPPgKP9kWjiIjIDlizJswFkkQ0A9jHzDqY2U6EBNGrJVcys2bAYcC/azi+2Jg4EebPD1VHVlrxlYiIiFRVvXgHINWkQ4eQQPr0U3jsMXjuuXA2tv32C4mkc86BPfaId5QiIpJM3OHXX+GbbyAnp/j10qWwYAHstVe8o5QS3H2zmV0GvA3UBR5396/NbHjk/ocjq54KvOPua+MUavVxh9tug733htNOi3c0IiIiKUfJo1RiBn36hMvdd8MLL4RE0vXXw5//HBprDx0KJ5wQeiaJiIgAbN4M33+/fYIoJ6f4CRl23jmc9fPww8N148bxi1nK5O6TgEkllj1c4vaTwJM1F1UMTZkC2dnhdGp168Y7GhERkZSjDEKq2nlnOP/8cMnJCVVIEybAv/8dKpDOPTckkvbdN96RiohITVmzBr79tjAxVJAk+u47yM8vXK9Vq5AcyswM1/vvH65bt9Z0IElMt90Wfm/POSfekYiIiKQkJY9qg06dQgPJv/0NJk0K1UjjxoVlhx4akkiDB+sbZBGRVJGbC3Pnbl9F9GORs7fXrRumnO2/P/zxj4UJok6doFmz+MUuUlkzZoTKo9tvhwYN4h2NiIhISlLyqDapXx9OPjlcli2Dp54KiaTzz4crroAzzwyJpIMP1jfLIiLJYtUqmDkzTNmZMSNc//BD4f0FU80OO6x4gmjvvWGnneIXt0h1ue022GUXuOiieEciIiKSspQ8qq1atQq9kK67DqZPh8cfh6wseOQROOAAuOACGDIEEv20vCIi1WXTJvj4Y3j3XfjkE2jZEvbZJ0zvLbhu0SK+yfW1a+HLL4sniubPL7y/fXvo2ROGD4f09PD3XFPNJJXl5MArr8CNN0KTJvGORkREJGWZJ9mp3DMyMjw7OzveYaSm1avDWdoeeww++yxUKp10UqhGOvZYNaAUkdTiDvPmhWTRu+/C1Kmwbl34W9e9e6jo+eGH0Ey6wC67FCaTiiaW9tmn+qd6bdgAs2cXTxR98w1s3Rrub9MGMjIKLwcdFBJeKcDMvnD3jHjHIcUl5Bhs6FB49llYvFhfeImIiOygssZgMas8MrPHgYHAf9y9cyn3G3APcAKwDjjP3WfGKp5Ul5UVvnRbsgTatoUxY0Kf00pp2hQuvDBcvv46VCM99RS89FL45vq88+CMM8I32UokiSSf3NxQWfPJJ5CWFqYu7bdfSHw0bBjv6GrGr7/C5MmFCaOffw7L9903TOE95hgYMCD8PYTQRHrRotBQev78wuvp0+GZZ0ICqsBuuxWvUipIKu29d9jfZdm0Cb76qnii6KuvChNXu+0WKooGDSpMFLVqVd17RyS5/Pgj/POfodJOiSMREZGYilnlkZn1B9YAT0VJHp0AXE5IHh0M3OPuB5e33YT81ivOsrJg2LDwhXmBtLRwttpKJ5BK2rQJXnstJJLeeit84924cfjg0rNn4aVDB02LEEk0ixfDtGkh0TFtWqiygZD83bKlcD2zcAzvt19hQqmgL85uuyX3sb1+fXjt774L77wDc+aE5S1awJFHhmTR0UeHrHtlbdgACxcWTyoVXP/yS/F127Qpnljae++QzCtIFM2eHf7eAjRvXryiKCMjPD6Z34dKUuVRYkq4MdiIEXDvveE4bNcu3tGIiIgkvbLGYDGdtmZm7YHXoySP/gFMdfd/RW5/Cwxw92VlbTPhBi4JoH378BmxpHbtwhfm1eann+C998KHnRkzQt+NjRvDfS1ahA84PXtCr17heo89qvHJRaRMW7eGisGCRNH06YVn1mraFPr2hUMOCWdY7NkzJI/mzw+nbc/JKX69YUPhdps1K0wkFU0q7bVXYjZb3ro1JGIKkkXTp4e/UzvtBP36hUTRMceEaWl16sQujry8kEgqmVT67jtYsaJwvaZNQzK+aKJIyXgljxJUQo3BcnPDQOe000KVtIiIiOywuExbq4DWQJFzBrM0sqzM5JFsb8mSyi2vstatQxPtIUPC7fz8cCrogmTSjBlw662FFQ1t2hSvTsrICP1CRGTHbdwYKlYKkkUffQQrV4b7WrUKSaJrrw3XXbqUPtW0R49wKWrr1pB0yskpnlR6912YMKFwvbp1oWPH4gmlgp9ruu/O0qWF09AmT4bly8Pyzp3hkktCsujQQ0PVZE1p0qT0/QvhQ++CBeHv4T77xDaJJZKq7r8/NJC/2rZLNwAAGeRJREFU/vp4RyIiIlIrxDN5VNrXqqWWQZnZMGAYQNuqTC1IcW3bll55FPNdVb9+4YejgtPjrlsXKpJmzIDPPw/Xr7xS+Jh99imeUOrevfxeICISmjd//HFhsujzzwsr/zp1Cr1wDj00VBftSOVKnTrh2/x27UKj/KJWrw7JpJLVSu+8UzjlCkIl4h/+AA0ahIqfktflLavIY1auhClTwnPn5ITn3X33EPMxx8BRRyVuT6AWLcJFRKpmzZowXe2kk+DAA+MdjYiISK0Qz+TRUmDPIrfbAD+XtqK7jwfGQyiZjn1oyWXMmNJ7Ho0ZE4dg0tLC1JB+/QqX/f57YRPYGTPggw9Co1kI1QudOxcmk7p2DdUBDRqEBr4NGhT/uZZP5ZAyrFkD778Pb78d+tzsv3/hpV275Gvy/tNPxaegzZkTmjPXqxcStpdeGpJF/frVXKPYpk0Lj9WitmwJGeyCaqWcHPjPf0JCadOmkORau7bw56LLi/5ctA9TRTRqBP37w3//d0gYde6svxEitcGjj4bpnzfcEO9IREREao149jw6EbiMwobZ97p7r/K2mVDz7RNItZxtrSb9/HPx6W4zZoQkU3kKqg6iJZfK+7lRozCFp2/fMA1PklfBadbffDM0c582LSQhGjcOl//8p3Ddhg3DlKqiCaX99w+VcA0axCf+rVvDmb9++CE0Jyt6mT+/sJywcWPo06ewX9HBB9fs9KuatGVLmA5bWoKp5LKddgpTYWvLWeJqGfU8SkwJMQbbtCn0XNtrL5g6Nb6xiIiIpJi4NMw2s38BA/j/7d1/kCTledjx73O3J6yVDEj8DnB7yEGxkQohvGBEgotKQnKHZJNEdgTeKsmSqs6oRFl2lRJRxlH8R64khBPZGCy0jrCNsxZOShKmVAhjqyTbMUJwRx0YdCL8qLvjDEL8KENgsdBxT/7o3uzcsL0/7qanp6e/n6qu6Xm7p/d5eWduXp55+33hWOAp4D8DGwAy84aICOA6YDMwD3wwM1fskYxEx0WDlwmPPQa7dhWT9f7DPxT/g/iDHxzefv/zl19eXFp748Zi1Mb55xfbmWcWozo0up5/vrhVaSFhtG9fUf72t8PmzbBlS9GmRxxR/Cq9a9drtz17Ft8DC/P29CeVfvzHF5dqP1SZRXJoISHUnyTas2fxtrMFJ5xQzIB/2mnFxPMXXABnneX7Up1j8mg0jUQf7Pd/Hz70oeJ7YPPmZmORJGnMNLbaWh1GouOi9nrlFdi5s5g75s47i0mGnyjvlpycLEZ1LCSTzjuvWDJbzcks2uv224v/UbjzzmJ0ypFHFnPabNlSzHFz6qkrX2vB/HwxV09/Uunhh4tRLwtOPvm1SaWf+InFpeszi9FN/aOGFpJEe/YcvGoZFLeXLSSHNm06eJuacv4vqWTyaDQ13gc7cADOOKMYRXzvvd6mKknSgJk8kqpkFitLLSST7ryzSFYszL1yxhmLyaTzz4e3vtXOat2ee66YBPn224v5i773vaL8ne9cHF103nnFhO2DtH8/PProa5NK3/1uMZ/Sgje9qUgCPf54MZKt17HHvjYptJAompoa39vNpAEzeTSaGu+DffnL8N73ws03w/ve11wckiSNKZNH0lq89FIxB9Pf/E2RTPrWtxbnYzrmmGL+mYVk0jnnOFrkcL36KuzYsTi66O67i1+X3/zmYhLkzZuLx6ZWzsosJq/uTSg980yRDOpPFL3xjc3EKI0Zk0ejqdE+WGYxOvi554qkvrfzSpI0cMv1wfzmlfq94Q1w4YXFBkUi46GHDh6d9NWvFscmJoo5aXrnTjr++IPnXFpqHqbVHKsq37+/mKtn3brisX9/uWOr2V+//vCXU9+wobhmlaeeOnh00bPPFiO6zjkHfv3Xi9FF55wzGiukRcAppxTbRRc1HY0kddM3vlH8sPP5z5s4kiSpAX77SitZt25xvpsPf7goe/ZZuOuuxXmTZmfht397sH93YuLg1eIWtomJIqH16qvF1rvf/7xqfxgjDicmlk4uRRTzC0Fx+9fFFxejiy66aHhLzkuS2uVTn4ITT4T3v7/pSCRJ6iSTR9KhOOYYePe7iw2KiZbvu6+4xe3555dO+hxxxNrKlxu5c7gyF5NJ/Qmm/fsXl0Rfbqn01RxfquyHPyw6/1u2FPMY1VlPSVL7bd8Of/EX8JnPFN+XkiRp6EweSYOwYQNMTxdbG0Qs3qImSdIou/pqOOoo+KVfajoSSZI6y5/8JUmSNJoeegi+9CX46EfhyCObjkaSpM4yeSRJkqTRdM01xa3cH/tY05FIktRpJo8kSZI0evbtg5tuKharOP74pqORJKnTTB5JkiRp9Hz2s8VCDh//eNORSJLUeSaPJEmSNFqeew4+/3m47DLYtKnpaCRJ6jyTR5IkSRot110HL70En/hE05FIkiRMHkmSJGmUvPQSXHst/MzPwNvf3nQ0kiQJk0eSJEkaJV/4Ajz7LFx5ZdORSJKkkskjSZIkjYZXXoHf/E244AI4//ymo5EkSaWJpgOQJEmSAPjiF+Hxx4vJsiVJ0shw5JFWZW6uWOxk3bricW6u6YgkSdJYOXAArr4azjwTNm9uOhpJktTDkUda0dwcbN0K8/PF8z17iucAMzPNxSVJksbIrbfCrl3wx38MEU1HI0mSejjySCu66qrFxNGC+fmiXJIk6bBlwqc+BW95C/z8zzcdjSRJ6uPII61o7961lUuSJK3JN78Jd98Nn/scTNg9lSRp1DjySCvauHFt5ZIkSWvy6U/DCSfAL/5i05FIkqQlmDzSirZtg8nJg8smJ4tySZKkw3LvvXDHHfCrvwo/8iNNRyNJkpZg8kgrmpmB2VmYmirmr5yaKp47WbYkSTpsn/40HHkkXH5505FIkqQK3lSuVZmZMVkkSZIGLBPOOgump+Goo5qORpIkVTB5JEmSpGZEwK/9WtNRSJKkFXjbmiRJkiRJkiqZPJIkSZIkSVIlk0eSJEmSJEmqZPJIkiRJkiRJlUweSZIkSZIkqZLJI0mSJEmSJFUyeSRJkiRJkqRKJo8kSZIkSZJUyeSRRsLcHGzaBOvWFY9zc01HJElSe0XE5oh4KCIeiYgrK865MCJ2RsSDEfGXw45RkiS1x0TTAUhzc7B1K8zPF8/37CmeA8zMNBeXJEltFBHrgeuBi4B9wD0RcWtmfqfnnKOB3wU2Z+beiDi+mWglSVIbOPJIjbvqqsXE0YL5+aJckiSt2bnAI5n5WGa+AtwMXNJ3zi8AX87MvQCZ+f0hxyhJklrE5JEat3fv2solSdKyTgYe73m+ryzr9VbgTRHxzYjYERHvH1p0kiSpdUweqXEbN66tXJIkLSuWKMu+5xPATwLvBv418J8i4q2vuVDE1ojYHhHbn3766cFHKkmSWsHkkRq3bRtMTh5cNjlZlEuSpDXbB5za8/wU4Iklzrk9M1/KzGeAvwLe0X+hzJzNzOnMnD7uuONqC1iSJI02k0dq3MwMzM7C1BREFI+zs06WLUnSIboHOD0iTouI1wGXArf2nfOnwAURMRERk8BPAbuGHKckSWqJWpNHKy0TWy4R+3y5TOzOiPhknfFodM3MwO7dcOBA8WjiSJKkQ5OZ+4ErgD+jSAj9z8x8MCIuj4jLy3N2AbcD9wN3A/89Mx9oKmZJkjTaJuq68GqWiS39dWa+p644JEmSuiYzbwNu6yu7oe/5NcA1w4xLkiS1U50jj1azTKwkSZIkSZJGWJ3Jo9UsEwvwroi4LyK+FhFvqzEeSZIkSZIkrVFtt62xumVi7wWmMvPFiLgYuAU4/TUXitgKbAXY6PrtkiRJkiRJQ1PnyKMVl4nNzBcy88Vy/zZgQ0Qc238hl4mVJEmSJElqRp3JoxWXiY2IEyMiyv1zy3ierTEmddjcHGzaBOvWFY9zc01HJEmSJEnS6KvttrXM3B8RC8vErgduXFgmtjx+A/BzwEciYj/wMnBpZvbf2iYdtrk52LoV5ueL53v2FM8BZmaai0uSJEmSpFEXbcvVTE9P5/bt25sOQy2zaVORMOo3NQW7dw87GknSciJiR2ZONx2HDmYfTJKk8bZcH6zO29akkbF379rKJUmSJElSweSROqFqkT4X75MkSZIkaXkmj9QJ27bB5OTBZZOTRbkkSZIkSapm8kidMDMDs7PFHEcRxePsrJNlS5IkSZK0ktpWW5NGzcyMySJJkiRJktbKkUeSJEmSJEmqZPJIkiRJkiRJlUweSQMyNwebNsG6dcXj3FzTEUmSJEmSdPic80gagLk52LoV5ueL53v2FM/BeZYkSZIkSe3myCNpAK66ajFxtGB+viiXJEmSJKnNTB5JA7B379rKJUmSJElqC5NH0gBs3Li2ckmSJEmS2sLkkTQA27bB5OTBZZOTRbkkSZIkSW1m8kgagJkZmJ2FqSmIKB5nZwc7WbaruUmSJEmSmuBqa9KAzMzUt7Kaq7lJkiRJkpriyCOpBVzNTZIkSZLUFJNHUgu4mpskSZIkqSkmj6QWcDU3SZIkSVJTTB5JLTCM1dyckFuSJEmStBSTR1IL1L2a28KE3Hv2QObihNwmkCRJkiRJJo+klpiZgd274cCB4nGQq6w5IbckSZIkqYrJI0lOyC1JkiRJqmTySNLQJuR2XiVJkiRJah+TR5KGNiG38ypJkiRJUvuYPJJU+4TcMJx5lRzZJEmSJEmDN9F0AJJGw8zMYJNF/eqeV2lhZNNCgmphZBPUWy9JkiRJGneOPJI0FHXPq+TIJkmSJEmqh8kjSUNR97xKwxrZVPecTSaoJEmSJI0ak0eShqLueZXGZWRT3Qkqk1OSJEmS1srkkaShmZmB3bvhwIHicZBzEbV9ZBPUn6Aah+TUMJJfJtgkSZKkg5k8kjQW2j6yCepPULU9OTWs5JcJtmavr27x/SRJUjtEZjYdw5pMT0/n9u3bmw5DUsf0r+YGxcimQSaoNm0qkhX9pqaKkVqHa926IiHSL6IYDXa46o6/7usP42/U/T5q+/UXRMSOzJwe3BU1CIPugw3r/SRJklZnuT6YySNJWqW5uWKUzt69xYijbdsG+z84df+PVNuTU3Vffxh/o+0JtmEk8MDk0agadB9sWO8nSZK0Osv1wbxtTZJWqc45mxauX+etd3XPC1X3rX3DuHWw7r9R962Jbb++usX3kyRJ7WHySJJGSJ0JqrYnp+q+/jD+RtsTbMNI4Kk7fD9JktQeJo8kqUPanJyq+/rD+BttT7ANI4Gn7vD9JElSezjnkSRJQzSMubPafH1wzqNRVUcfbBjvJ0mStDpOmC1JklrD5NFosg8mSdJ4c8JsSZIkSZIkHRKTR5IkSZIkSapUa/IoIjZHxEMR8UhEXLnE8YiIa8vj90fE2XXGI0mSJEmSpLWpLXkUEeuB64EtwBnAZRFxRt9pW4DTy20r8Lm64pEkSeqKVfyAd2FEPB8RO8vtk03EKUmS2mGixmufCzySmY8BRMTNwCXAd3rOuQS4KYtZu++KiKMj4qTMfLLGuCRJksZWzw94FwH7gHsi4tbM/E7fqX+dme8ZeoCSJKl16rxt7WTg8Z7n+8qytZ4jSZKk1fv/P+Bl5ivAwg94kiRJh6TO5FEsUZaHcA4RsTUitkfE9qeffnogwUmSJI2p1f44966IuC8ivhYRb1vqQvbBJEkS1Js82gec2vP8FOCJQziHzJzNzOnMnD7uuOMGHqgkSdIYWc2Pc/cCU5n5DuB3gFuWupB9MEmSBPXOeXQPcHpEnAb8HXAp8At959wKXFHOh/RTwPMrzXe0Y8eOZyJiTx0Bj6hjgWeaDmKIulZfsM5d0LX6gnXugjrrO1XTdbtixR/nMvOFnv3bIuJ3I+LYzKxs0471wbr2eQbr3AVdqy9Y5y7oWn2hoT5YbcmjzNwfEVcAfwasB27MzAcj4vLy+A3AbcDFwCPAPPDBVVy3Uz97RcT2zJxuOo5h6Vp9wTp3QdfqC9a5C7pW35ZZ8Qe8iDgReCozMyLOpRiN/uxyF+1SH6yL72/rPP66Vl+wzl3QtfpCc3Wuc+QRmXkbRYKot+yGnv0EPlpnDJIkSV2yyh/wfg74SETsB14GLi37ZZIkSa9Ra/JIkiRJw7eKH/CuA64bdlySJKmd6pwwW4Mx23QAQ9a1+oJ17oKu1Rescxd0rb7qli6+v63z+OtafcE6d0HX6gsN1TkcoSxJkiRJkqQqjjySJEmSJElSJZNHDYuIUyPiGxGxKyIejIiPLXHOhRHxfETsLLdPNhHrIEXE7oj427I+25c4HhFxbUQ8EhH3R8TZTcQ5KBHxT3rab2dEvBARv9J3TuvbOSJujIjvR8QDPWVvjog/j4iHy8c3Vbx2c0Q8VLb5lcOL+tBV1PeaiPhu+b79SkQcXfHaZT8Do6qizr8REX/X8969uOK1rWtjqKzzn/TUd3dE7Kx4bevauep7aZw/y+om+2D2wXrOaXU7d63/BfbBesrGtg/Wtf4XtKAPlpluDW7AScDZ5f6PAv8HOKPvnAuBrzYd64DrvRs4dpnjFwNfAwI4D/h20zEPsO7rge8BU+PWzsBPA2cDD/SUfQa4sty/Eri64r/Jo8BbgNcB9/V/DkZxq6jvvwImyv2rl6pveWzZz8CobhV1/g3g4yu8rpVtXFXnvuP/FfjkuLRz1ffSOH+W3bq52QerPG4frGVb1/pfy9TZPtjSr2tlO3et/1XGPdJ9MEceNSwzn8zMe8v9/wvsAk5uNqqRcAlwUxbuAo6OiJOaDmpA/gXwaGbuaTqQQcvMvwKe6yu+BPjDcv8PgX+zxEvPBR7JzMcy8xXg5vJ1I22p+mbmHZm5v3x6F3DK0AOrUUUbr0Yr2xiWr3NEBPDvgS8ONagaLfO9NLafZXWTfbBK9sFapmv9L7APtkatbOeu9b9g9PtgJo9GSERsAt4JfHuJw++KiPsi4msR8bahBlaPBO6IiB0RsXWJ4ycDj/c838f4dOgupfofunFrZ4ATMvNJKP5BBI5f4pxxbe8PUfx6u5SVPgNtc0U5TPzGiqG049rGFwBPZebDFcdb3c5930td/ixrzNkHO8g4f4671Afr+r/Z9sEWjWM7j3X/C0azD2byaERExBuBLwG/kpkv9B2+l2J47TuA3wFuGXZ8NfinmXk2sAX4aET8dN/xWOI1rV8aMCJeB/ws8L+WODyO7bxaY9feEXEVsB+Yqzhlpc9Am3wO+DHgLOBJimHE/caujUuXsfyvXq1t5xW+lypftkTZOLSzxph9MPtgjGc7r8a4trV9sIONYzuPbf8LRrcPZvJoBETEBoo3x1xmfrn/eGa+kJkvlvu3ARsi4tghhzlQmflE+fh94CsUw+x67QNO7Xl+CvDEcKKr1Rbg3sx8qv/AOLZz6amF4e7l4/eXOGes2jsiPgC8B5jJ8ibkfqv4DLRGZj6Vma9m5gHg91i6LmPVxgARMQH8O+BPqs5paztXfC917rOs8WcfzD4YjGc709F/s+2DjX8fbJz7XzDafTCTRw0r79f8ArArM/9bxTknlucREedStNuzw4tysCLiDRHxowv7FJPbPdB32q3A+6NwHvD8wlC9lqvMko9bO/e4FfhAuf8B4E+XOOce4PSIOK38ZfDS8nWtExGbgU8AP5uZ8xXnrOYz0Bp9c2H8W5auy9i0cY9/CXw3M/ctdbCt7bzM91KnPssaf/bB7IMtGLd2LnXu32z7YJ3pg41l/wta0AfLAc6+7XZIM6r/M4rhZPcDO8vtYuBy4PLynCuABylmTL8LOL/puA+zzm8p63JfWa+ryvLeOgdwPcWM8X8LTDcd9wDqPUnRETmqp2ys2pmiU/Yk8EOK7PeHgWOArwMPl49vLs/9R8BtPa+9mGJFgUcX3hOjvlXU9xGK+40XPs839Ne36jPQhq2izn9Ufk7vp/iSOmlc2riqzmX5Hyx8fnvObX07L/O9NLafZbdubsu818fqu7mvzvbBFsvGpp0rvpvH+t/sijrbBxujPthS9S3L/4Ax7H+VsY90HyzKPyJJkiRJkiS9hretSZIkSZIkqZLJI0mSJEmSJFUyeSRJkiRJkqRKJo8kSZIkSZJUyeSRJEmSJEmSKpk8klSriHg1Inb2bFcO8NqbIuKBQV1PkiRpXNgHkzRIE00HIGnsvZyZZzUdhCRJUsfYB5M0MI48ktSIiNgdEVdHxN3l9o/L8qmI+HpE3F8+bizLT4iIr0TEfeV2fnmp9RHxexHxYETcERGvL8//5Yj4TnmdmxuqpiRJ0kixDybpUJg8klS31/cNmX5fz7EXMvNc4Drgt8qy64CbMvNMYA64tiy/FvjLzHwHcDbwYFl+OnB9Zr4N+HvgvWX5lcA7y+tcXlflJEmSRpR9MEkDE5nZdAySxlhEvJiZb1yifDfwzzPzsYjYAHwvM4+JiGeAkzLzh2X5k5l5bEQ8DZySmT/oucYm4M8z8/Ty+SeADZn5XyLiduBF4Bbglsx8seaqSpIkjQz7YJIGyZFHkpqUFftV5yzlBz37r7I4l9u7geuBnwR2RIRzvEmSJBXsg0laE5NHkpr0vp7Hb5X7dwKXlvszwP8u978OfAQgItZHxJFVF42IdcCpmfkN4D8CRwOv+eVNkiSpo+yDSVoTs8CS6vb6iNjZ8/z2zFxYKvaIiPg2RSL7srLsl4EbI+I/AE8DHyzLPwbMRsSHKX7d+gjwZMXfXA/8j4g4Cgjgs5n59wOrkSRJ0uizDyZpYJzzSFIjyvvtpzPzmaZjkSRJ6gr7YJIOhbetSZIkSZIkqZIjjyRJkiRJklTJkUeSJEmSJEmqZPJIkiRJkiRJlUweSZIkSZIkqZLJI0mSJEmSJFUyeSRJkiRJkqRKJo8kSZIkSZJU6f8BHodZeZcLf7AAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 1440x360 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "def show_loss_acc(history, epochs):\n",
    "    import matplotlib.pyplot as plt\n",
    "    %matplotlib inline\n",
    "    plt.figure(figsize=(20,5)) #其中(5, 3)用于控制图片的大小\n",
    "    \n",
    "    lst_loss = history['loss']\n",
    "    lst_valloss = history['val_loss']\n",
    "    lst_acc = history['acc']\n",
    "    lst_valacc = history['val_acc']\n",
    "    \n",
    "    epochs = range(1, epochs + 1)\n",
    "    \n",
    "    plt.subplot(1,2,1)\n",
    "    plt.plot(epochs, lst_loss, 'bo', label='Training loss') #'bo': blue solid pointer\n",
    "    plt.plot(epochs, lst_valloss, 'r', label='Validation loss') # 'b': blue line\n",
    "    plt.title('Training and validation loss')\n",
    "    plt.xlabel('Epochs')\n",
    "    plt.ylabel('Loss')\n",
    "    plt.legend()\n",
    "\n",
    "    plt.subplot(1,2,2)\n",
    "    plt.plot(epochs, lst_acc, 'bo', label='Training acc') #'ro': red solid pointer\n",
    "    plt.plot(epochs, lst_valacc, 'r', label='Validation acc') # 'r': red line\n",
    "    plt.title('Training and validation Accuracy')\n",
    "    plt.xlabel('Epochs')\n",
    "    plt.ylabel('Loss')\n",
    "    plt.legend()\n",
    "\n",
    "    plt.show()\n",
    "show_loss_acc(hisotry.history, 20)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.3 validation the model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(2246, 46)\n",
      "[[2.05871561e-06 9.59464342e-06 1.51893715e-08 9.72433388e-01\n",
      "  2.25013644e-02 3.60808237e-08 1.06578266e-08 3.86688782e-07\n",
      "  1.43533526e-03 8.28377988e-09 7.66471601e-07 6.80613273e-04\n",
      "  2.12956502e-06 4.91617311e-06 3.44465150e-07 3.33361494e-09\n",
      "  1.11133224e-04 7.04719582e-07 6.01797819e-06 3.89827066e-04\n",
      "  2.36684340e-03 2.08327219e-05 9.34459834e-08 2.53462758e-07\n",
      "  7.32115435e-09 1.60777449e-06 2.19149010e-09 1.93618860e-07\n",
      "  6.14914711e-07 8.43052078e-07 2.51885012e-06 1.81655029e-08\n",
      "  2.74055060e-06 1.85571764e-07 7.07928621e-07 2.33133122e-08\n",
      "  2.31549639e-05 6.21739318e-08 1.64467366e-07 4.66840433e-08\n",
      "  8.65254624e-09 1.86576145e-07 1.01865172e-09 2.01139261e-09\n",
      "  3.36114014e-12 2.57216669e-07]\n",
      " [3.29050927e-05 1.59534309e-02 1.71515532e-03 1.19728329e-05\n",
      "  3.30529641e-03 6.31161453e-03 8.79939478e-07 7.32655972e-05\n",
      "  1.96419896e-05 2.62674614e-04 9.45731580e-01 7.95378175e-04\n",
      "  1.16166475e-05 3.29575450e-05 2.03221589e-02 4.40240292e-05\n",
      "  4.46700171e-04 9.99635148e-08 2.59308035e-06 2.36411463e-03\n",
      "  4.26943239e-04 1.11249850e-04 2.14413536e-04 1.20522407e-06\n",
      "  2.12267070e-04 2.66338793e-06 3.57941978e-08 1.86648194e-05\n",
      "  2.77365383e-04 1.37565785e-05 2.77932530e-04 1.46500929e-06\n",
      "  8.36011823e-05 6.69559377e-05 2.88408296e-06 4.49705226e-07\n",
      "  5.80777596e-05 9.97258576e-06 1.30567700e-04 5.18847571e-07\n",
      "  3.58079124e-04 5.06024116e-06 1.32507674e-04 1.54652182e-04\n",
      "  3.70744750e-08 5.08515711e-07]\n",
      " [1.95156261e-02 8.72993469e-01 4.25009197e-03 1.71600021e-02\n",
      "  1.57237882e-04 1.97989438e-02 8.45456088e-06 7.60318362e-04\n",
      "  8.67599301e-05 4.91386279e-03 2.85926450e-04 4.63868817e-03\n",
      "  5.93737877e-06 1.31686684e-03 4.06192034e-04 3.41093575e-04\n",
      "  5.33151627e-03 5.60640401e-05 4.61386488e-04 7.38765229e-04\n",
      "  4.22590319e-03 1.21385709e-03 1.49521441e-03 4.56090056e-05\n",
      "  8.17652326e-03 5.99189807e-05 5.92243259e-06 2.48299143e-03\n",
      "  5.93627244e-03 2.79306587e-05 1.01031446e-05 8.64827816e-05\n",
      "  7.89444195e-04 2.61208188e-04 5.82776483e-05 6.90154120e-05\n",
      "  2.57766596e-03 9.58479286e-05 3.41911032e-03 5.93557052e-05\n",
      "  2.34524283e-04 1.37787778e-02 1.59503354e-04 1.29624060e-03\n",
      "  5.00663759e-07 2.06520199e-04]\n",
      " [9.44289752e-07 1.42533145e-05 1.35969424e-06 7.87161291e-02\n",
      "  7.87185311e-01 3.87017417e-06 8.92138451e-06 1.25016095e-05\n",
      "  1.04589672e-04 3.99717749e-07 7.94317202e-06 6.78477008e-05\n",
      "  2.55486407e-06 1.32530788e-03 1.46959144e-06 3.32079338e-07\n",
      "  1.30925253e-01 1.54362264e-04 4.43917406e-06 5.99753912e-05\n",
      "  3.65245709e-04 2.01801431e-05 7.03717978e-06 3.34380493e-05\n",
      "  5.07816412e-06 4.17049487e-05 4.13931573e-08 1.31121733e-05\n",
      "  4.25100825e-06 8.78669107e-06 4.05481725e-04 1.27187988e-04\n",
      "  1.21759535e-04 6.59441284e-05 1.07575088e-05 1.41434396e-06\n",
      "  5.43680399e-05 5.29742574e-05 5.32407057e-07 3.91870308e-05\n",
      "  9.79371109e-08 2.09465597e-05 4.61162344e-08 7.42238342e-07\n",
      "  1.53778557e-09 1.82078077e-06]]\n"
     ]
    }
   ],
   "source": [
    "predictions = model.predict(x_test)\n",
    "print(predictions.shape)\n",
    "\n",
    "print(predictions[:4])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
